// # https://github.com/microsoft/TypeScript/pull/30215

declare function pipe<A extends any[], B, C>(
  ab: (...args: A) => B,
  bc: (b: B) => C,
): (...args: A) => C;

declare function list<T>(a: T): T[];
declare function box<V>(x: V): { value: V };

const listBox = pipe(list, box); // <T>(a: T) => { value: T[] }
//      ^?
const boxList = pipe(box, list); // <V>(x: V) => { value: V }[]
//      ^?

const x1 = listBox(42); // { value: number[] }
//            ^?
const x2 = boxList('hello'); // { value: string }[]
//            ^?

{
  const flip = // =>

      <A, B, C>(f: (a: A, b: B) => C) =>
      (b: B, a: A) =>
        f(a, b);
  const zip = <T, U>(x: T, y: U): [T, U] => [x, y];
  //     ^?
  const flipped = flip(zip); // <T, U>(b: U, a: T) => [T, U]
  //     ^?

  const t1 = flipped(10, 'hello'); // [string, number]
  //     ^?
  const t2 = flipped(true, 0); // [number, boolean]
  //     ^?
}

function ap<A>(fn: (x: A) => A, x: A): (a: A) => boolean {
  return (y) => y === x;
}
declare function id<A>(x: A): A;
// @ts-expect-error
let w = ap(id, 10)('s');

{
  function ap<A>(fn: (x: A) => A, x: A[]): (a: A) => void {
    return (a) => x.push(a);
  }
  function id<A>(x: A): A {
    return x;
  }
  const arr = [10] as const satisfies [number];
  // @ts-expect-error
  ap(id, arr)('s');
  // @ts-expect-error
  // prints a string from a number array
  console.log(arr[1]);
}

type Currying<T extends unknown[], U> = T extends []
  ? U
  : {
      <_Args extends unknown[]>(
        ...args: _Args /*反传*/
      ): T extends [..._Args, ...infer R] ? Currying<R, U> : never;
    };

declare function DynamicParamsCurrying<T extends any[], U>(
  fn: (...args: T) => U,
): Currying<T, U>;

const f = DynamicParamsCurrying(
  (...a: [a: number, b: boolean, c: string]) => 1,
);
f(1, 2);
